import logging
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.db import transaction
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework.authentication import TokenAuthentication
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from api_test.common.api_response import JsonResponse
from api_test.common.common import record_dynamic
from api_test.models import Project, ApiInfo, ApiCaseInfo
from api_test.serializers import ApiCaseInfoDeserializer, ApiCaseInfoSerializer

logger = logging.getLogger(__name__)  # 这里使用 __name__ 动态搜索定义的 logger 配置，这里有一个层次关系的知识点。


class CaseInfoList(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    @swagger_auto_schema(manual_parameters=[
        openapi.Parameter(name="id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="case id"),
        openapi.Parameter(name="project_id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="项目id"),
        openapi.Parameter(name="api_id", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER, description="api id"),
        openapi.Parameter(name="name", in_=openapi.IN_QUERY, type=openapi.TYPE_STRING, description="case name"),
    ])
    def get(self, request):
        """
        获取接口的case信息
        """
        project_id = request.GET.get("project_id")
        case_id = request.GET.get("id")
        api_id = request.GET.get("api_id")
        name = request.GET.get("name")
        page_size = int(request.GET.get("page_size", 1000))
        page = int(request.GET.get("page", 1))

        if api_id and not api_id.isdecimal():
            return JsonResponse(code="999996", msg="参数有误!")
        if not isinstance(page, int) or not isinstance(page_size, int):
            return JsonResponse(code="999996", msg="参数有误!")
        try:
            if api_id:
                api_data = ApiInfo.objects.get(id=api_id, status=True)
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="接口不存在or已禁用!")

        try:
            obi = ApiCaseInfo.objects.filter(status=True)
            if project_id:
                obi = obi.filter(project_id=project_id)
            if api_id:
                obi = obi.filter(api_id=api_id)
            if case_id:
                obi = obi.filter(id=case_id)
            if name:
                obi = obi.filter(name__contains=name)
            obi = obi.order_by("id")

            paginator = Paginator(obi, page_size)  # paginator对象
            page_sizes = paginator.num_pages  # 总页数
            total = paginator.count  # 总数
            try:
                obm = paginator.page(page)
            except PageNotAnInteger:
                obm = paginator.page(1)
            except EmptyPage:
                obm = paginator.page(paginator.num_pages)
            serialize = ApiCaseInfoSerializer(obm, many=True)

            return JsonResponse(data={"data": serialize.data, "page_sizes": page_sizes, "total": total},
                                code="999999", msg="成功!")
        except ObjectDoesNotExist:
            return JsonResponse(code="999990", msg="case不存在!")


class AddApiCase(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        """
        try:
            # 校验必传参数 data可以为空
            if not data.get("api_id") or not data.get("name"):
                return JsonResponse(code="999996", msg="参数有误!")
            if not isinstance(data["api_id"], int):
                return JsonResponse(code="999996", msg="参数有误!")
            if data.get("data") and not isinstance(data["data"], str):  # 将前端传来的dict类型转为str类型
                data["data"] = str(data["data"])
            else:
                data["data"] = '{}'
            if data.get("header") and not isinstance(data["header"], str):
                data["header"] = str(data["header"])
            else:
                data["header"] = '[]'
        except KeyError:
            return JsonResponse(code="999996", msg="参数有误!")

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['api_id', 'name'],
        properties={
            'project_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="项目id"),
            'api_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="接口id"),
            'name': openapi.Schema(type=openapi.TYPE_STRING, description="case名称"),
            'data': openapi.Schema(type=openapi.TYPE_OBJECT, description="case参数"),
            'header': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Items(type=openapi.TYPE_OBJECT), description="case请求头参数"),
            'description': openapi.Schema(type=openapi.TYPE_STRING, description="case描述"),
        },
    ))
    def post(self, request):
        """
        新增接口case
        """
        data = JSONParser().parse(request)
        result = self.parameter_check(data)
        if result:
            return result
        data["userUpdate"] = request.user.pk
        data['description'] = data.get('description', None)
        try:
            obp = Project.objects.get(id=data["project_id"], status=True)
            obj = ApiInfo.objects.get(id=data["api_id"], status=True)
            if not request.user.is_superuser and obp.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目or接口 不存在or已禁用!")
        count = ApiCaseInfo.objects.filter(name=data["name"], api=data["api_id"]).count()
        if count > 0:
            return JsonResponse(code="999997", msg="存在相同名称!")
        else:
            with transaction.atomic():  # 执行错误后，帮助事务回滚
                serialize = ApiCaseInfoDeserializer(data=data)
                if serialize.is_valid():
                    try:
                        serialize.save(api=obj, project=obp)
                    except KeyError:
                        serialize.save(api=obj, project=obp)

                    record_dynamic(project=obj.project_id,
                                   api=data["api_id"],
                                   _type="新增", operationObject="接口case", user=request.user.pk,
                                   data="新增接口case“%s”" % data["name"])
                    return JsonResponse(code="999999", msg="成功!", data={"case_id": serialize.data.get("id")})
                else:
                    print(serialize.errors)
                return JsonResponse(code="999996", msg="参数有误!")


class UpdateApiCase(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        """
        try:
            # 校验必传参数
            if not data.get("api_id") or not data.get("name") or not data.get("id"):
                return JsonResponse(code="999996", msg="参数有误!")
            if not isinstance(data["api_id"], int) or not isinstance(data["id"], int):
                return JsonResponse(code="999996", msg="参数有误!")
            if data.get("data") and not isinstance(data["data"], str):  # 将前端传来的dict类型转为str类型
                data["data"] = str(data["data"])
            else:
                data["data"] = '{}'
            if data.get("header") and not isinstance(data["header"], str):
                data["header"] = str(data["header"])
            else:
                data["header"] = '[]'
        except KeyError:
            return JsonResponse(code="999996", msg="参数有误!")

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['api_id', 'name', 'project_id'],
        properties={
            'id': openapi.Schema(type=openapi.TYPE_INTEGER, description="用例id"),
            'project_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="项目id"),
            'api_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="接口id"),
            'name': openapi.Schema(type=openapi.TYPE_STRING, description="case名称"),
            'data': openapi.Schema(type=openapi.TYPE_OBJECT, description="case参数"),
            'header': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Items(type=openapi.TYPE_OBJECT), description="case请求头参数"),
            'description': openapi.Schema(type=openapi.TYPE_STRING, description="case描述"),
        },
    ))
    def post(self, request):
        """
        更新接口case
        """
        data = JSONParser().parse(request)
        result = self.parameter_check(data)
        if result:
            return result
        try:
            obj = ApiInfo.objects.get(id=data["api_id"], status=True)
            if not request.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="接口不存在or已禁用!")
        count = ApiCaseInfo.objects.filter(name=data["name"]).exclude(id=data["id"]).count()
        if count > 0:
            return JsonResponse(code="999997", msg="存在相同名称!")
        try:
            obi = ApiCaseInfo.objects.get(id=data["id"])
        except ObjectDoesNotExist:
            return JsonResponse(code="999990", msg="case不存在!")

        with transaction.atomic():  # 执行错误后，帮助事务回滚
            serialize = ApiCaseInfoDeserializer(data=data)
            if serialize.is_valid():

                serialize.update(instance=obi, validated_data=data)

                record_dynamic(project=obj.project_id, api=data["api_id"], _type="修改",
                               operationObject="接口case", user=request.user.pk, data="修改接口case“%s”" % data["name"])
                return JsonResponse(code="999999", msg="成功!")
            else:
                return JsonResponse(code="999996", msg="失败!")


class DelApiCase(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = ()

    def parameter_check(self, data):
        """
        校验参数
        """
        try:
            # 校验project_id, id类型为int
            if not data.get("project_id") or not data.get("ids"):
                return JsonResponse(code="999996", msg="参数有误!")
            if not isinstance(data["project_id"], int) or not isinstance(data["ids"], list):
                return JsonResponse(code="999996", msg="参数有误!")
            for i in data["ids"]:
                if not isinstance(i, int):
                    return JsonResponse(code="999996", msg="参数有误!")
        except KeyError:
            return JsonResponse(code="999996", msg="参数有误!")

    @swagger_auto_schema(request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        required=['project_id', 'ids'],
        properties={
            'project_id': openapi.Schema(type=openapi.TYPE_INTEGER, description="项目id"),
            'ids': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Items(type=openapi.TYPE_INTEGER),
                                  description="待删除待用例id列表"),
        },
    ))
    def post(self, request):
        """
        删除用例
        """
        data = JSONParser().parse(request)
        result = self.parameter_check(data)
        if result:
            return result
        try:
            pro_data = Project.objects.get(id=data["project_id"], status=True)
            if not request.user.is_superuser and pro_data.user.is_superuser:
                return JsonResponse(code="999983", msg="无操作权限！")
        except ObjectDoesNotExist:
            return JsonResponse(code="999995", msg="项目不存在or已禁用!")

        for j in data["ids"]:
            obj = ApiCaseInfo.objects.get(id=j)
            if obj:
                obj.status = False
                obj.save()

                record_dynamic(project=data["project_id"], api=obj.api_id,
                               _type="禁用", operationObject="用例", user=request.user.pk, data="禁用用例“%s”" % obj.name)
        return JsonResponse(code="999999", msg="成功!")

